package redis.clients.jedis;

import java.util.List;

import org.apache.commons.pool2.impl.GenericObjectPoolConfig;

import java.util.Set;

import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisException;

public class JedisSlotBasedConnectionHandler extends JedisClusterConnectionHandler {

    public JedisSlotBasedConnectionHandler(Set<HostAndPort> nodes,
                                           final GenericObjectPoolConfig poolConfig, int timeout) {
        this(nodes, poolConfig, timeout, timeout);
    }

    public JedisSlotBasedConnectionHandler(Set<HostAndPort> nodes,
                                           final GenericObjectPoolConfig poolConfig, int connectionTimeout, int soTimeout) {
        //(4)调用父类构造方法
        super(nodes, poolConfig, connectionTimeout, soTimeout);
    }

    //随机去一个JedisPool
    @Override
    public Jedis getConnection() {
        // In antirez's redis-rb-cluster implementation,
        // getRandomConnection always return valid connection (able to
        // ping-pong)
        // or exception if all connections are invalid

        //链接进行随机重排
        List<JedisPool> pools = getShuffledNodesPool();

        for (JedisPool pool : pools) {
            System.out.println("----"+pool);
            Jedis jedis = null;
            try {
                jedis = pool.getResource();

                if (jedis == null) {
                    continue;
                }

                String result = jedis.ping();
                if (result.equalsIgnoreCase("pong")) {
                    return jedis;
                }

                jedis.close();
            } catch (JedisException ex) {
                if (jedis != null) {
                    jedis.close();
                }
            }
        }

        throw new JedisConnectionException("no reachable node in cluster");
    }

    //根据key计算的slot对应的JedisPool
    @Override
    public Jedis getConnectionFromSlot(int slot) {
        JedisPool connectionPool = cache.getSlotPool(slot);
        if (connectionPool != null) {
            // It can't guaranteed to get valid connection because of node
            // assignment
            return connectionPool.getResource();
        } else {
            return getConnection();
        }
    }
}
